package shapes.shapes2D.polygon 
{
	import flash.display.Graphics;
	import flash.geom.Point;
	import shapes.shapes2D.BaseShape;
	import shapes.shapes2D.Line;
	/**
	 * @author Nicolas Barradeau
	 * http://en.nicoptere.net
	 */
	public class RegularPolygon extends BaseShape
	{
		private var _radius:Number = 20;
		private var _sides:Number = 5;
		private var _points:Vector.<Point>;
		
		public function RegularPolygon( x:Number = 0, y:Number = 0, radius:Number = 20, sides:int = 5 ) 
		{
			this.x = x;
			this.y = y;
			_radius = radius;
			_sides = sides;
			resetShape();
		}
		
		private function resetShape():void
		{
			
			points = new Vector.<Point>();
			var i:int = 0;
			var angle:Number;
			var angleStep:Number = ( Math.PI * 2 ) / sides;
			for ( i = 0; i < sides; i++ )
			{
				angle = angleStep * i - Math.PI * .5;
				points.push( new Point( Math.cos( angle ) * radius, Math.sin( angle ) * radius ) );
			}
			
		}
		
		public function getEdgeDistanceToPoint( p:Point ):Point
		{
			
			var a:Number = Math.atan2( p.y, p.x );
			var d:Number = getCenterToEdgeDistance( a );
			p.x = x + Math.cos( a ) * d;
			p.y = y + Math.sin( a ) * d;
			return p;
			
		}
		
		public function getCenterToEdgeDistance( angle:Number ):Number
		{
			if (_sides == 1) return _radius;
			angle += Math.PI * .5;
		 	var a:Number = ( angle - ( rotation / 180 * Math.PI ) );
		 	while (a < 0 ) a += Math.PI * 2;
			
			a = a % (Math.PI * 2 / _sides);
		 	if (a >= 0 && a <= Math.PI / _sides ) a = Math.PI / _sides - a;
			if (a > Math.PI / _sides && a <= Math.PI * 2 / _sides) a = a - Math.PI * 1 / _sides;
		 	
			return _radius * Math.cos( Math.PI / _sides ) / Math.cos( a );
			
		}
		
		public function draw( graphics:Graphics = null ):void
		{
			var ox:Number = x;
			var oy:Number = y;
			if ( graphics == null ) 
			{
				graphics = this.graphics;
				graphics.clear();
				graphics.lineStyle( strokeWidth, strokeColor, strokeAlpha );
				graphics.beginFill( fillColor, fillAlpha );
				ox = oy = 0;
			
			}
			
			var p:Point = points[ 0 ];
			graphics.moveTo( ox + p.x, oy + p.y );
			for each( p in points )
			{
				graphics.lineTo( ox + p.x, oy + p.y );
			}
			
		}
		
		/**
		 * determine si un point est à l'intérieur du polygone
		 * @param	p
		 * @return
		 */
		public function contains( p:Point ):Boolean
		{
			p.x -= x;
			p.y -= y;
			var i:int, counter:int = 0;
			var xinters:Number = 0;
			var p1:Point ,p2:Point ;
			var N:int = _points.length;
			
			p1 = _points[0];
			for (i = 1; i <= N; i++) 
			{
				p2 = _points[i % N];
				if ( p.y > ( ( p1.y < p2.y ) ? p1.y : p2.y ) ) //MIN( p1.y, p2.y )
				{
					if (p.y <= ( ( p1.y > p2.y ) ? p1.y : p2.y ) )//MAX(p1.y, p2.y) 
					{
						if (p.x <= ( ( p1.x > p2.x ) ? p1.x : p2.x ) ) //MAX(p1.x, p2.x)
						{
							if ( p1.y != p2.y ) 
							{
								xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
								if (p1.x == p2.x || p.x <= xinters)
								{
									counter++;
								}
							}
						}
					}
				}
				p1 = p2;
			}
			
			if (counter % 2 == 0)
			{
				return false;
			}
			return true;
		}
		
		
		
		public function get points():Vector.<Point> { return _points; }
		
		public function set points(value:Vector.<Point>):void 
		{
			_points = value;
		}
		
		public function get radius():Number { return _radius; }
		
		public function set radius(value:Number):void 
		{
			_radius = value;
			resetShape();
		}
		
		public function get sides():Number { return _sides; }
		
		public function set sides(value:Number):void 
		{
			_sides = value;
			resetShape();
		}
	}

}